
package cfar.actors;

import cfar.actors.distributed.Signal;

import fj.F;
import fj.data.List;

import static cfar.actors.Communication.*;

/**
 *
 * @author badi
 */
public abstract class LocalActor extends Actor implements Tellable, Recievable {

    List<Message> mailbox;


    public LocalActor(){
        mailbox = List.nil();
    }

    protected Message next_message() {

        while(mailbox.isEmpty()){
            Thread.yield();
        }

        Message msg = mailbox.head();
        List<Message> tmp_box = mailbox.tail();

        synchronized (mailbox){
            mailbox = tmp_box;
        }

        return msg;
    }

    public void tell(Message msg) {
        List<Message> tmp_box = mailbox.snoc(msg);

        synchronized (mailbox){
            mailbox = tmp_box;
        }
    }

    protected  void cleanup() {
        if(mailbox.isNotEmpty()){
            mailbox.map(new F() {

                public Void f(Object a) {
                    act((Message) a);
                    return null;
                }
            });
        }
    }


    protected void run_actor(){

        boolean running = true;
        while(running){
            Message msg = next_message();

            if(msg.signal instanceof Signal.Stop){
                cleanup();
                running = false;
            }

            else act(msg);
        }
    }

}
